package com.jews.securityleam.authentication.sms;

import com.jews.securityleam.authentication.model.AuthResponse;
import com.jews.securityleam.domain.account.service.IAccountService;
import com.jews.securityleam.domain.message.bean.dto.CheckVerifyCodeDto;
import com.jews.securityleam.domain.message.service.IVerifyRecordService;
import com.jews.securityleam.infrastructure.constants.CodeEnum;
import com.jews.securityleam.starter.base.LoginSuccessToken;
import com.jews.securityleam.starter.config.AuthErrorMsg;
import com.jews.securityleam.starter.exception.CustomAuthenticationException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import java.util.Objects;

/**
 * @author JewsChen
 * @title: SmsAuthenticationProvider
 * @date 2023-06-19 1:09
 */
@Component
@Slf4j
@RequiredArgsConstructor
public class SmsAuthenticationProvider implements AuthenticationProvider {

    private final IVerifyRecordService verifyRecordService;
    private final IAccountService accountService;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        SmsToken token = (SmsToken) authentication;
        if (Objects.isNull(token) || ObjectUtils.isEmpty(token.getSmsAuthRequest().getPhone()) ||
                ObjectUtils.isEmpty(token.getSmsAuthRequest().getVerifyCode())) {
            throw new BadCredentialsException(AuthErrorMsg.passwordIncorrect.getName());
        }

        // 效验验证码
        CheckVerifyCodeDto checkVerifyCode = new CheckVerifyCodeDto();
        checkVerifyCode.setAccount(token.getSmsAuthRequest().getPhone());
        checkVerifyCode.setVerifyCode(token.getSmsAuthRequest().getVerifyCode());
        boolean isSuccess = verifyRecordService.checkVerifyCode(checkVerifyCode);

        // 根据手机号颁发token
        if (isSuccess) {
            AuthResponse tokenResult = accountService.assignTokenDirectByPhone(token.getSmsAuthRequest().getPhone());
            if (Objects.nonNull(tokenResult)) {
                return new LoginSuccessToken(tokenResult.getToken(), tokenResult.getUserName());
            }
        }

        // 这里最好根据每个业务错误抛异常
        throw new CustomAuthenticationException(CodeEnum.SystemError.getCode(), CodeEnum.SystemError.getName());
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return SmsToken.class.isAssignableFrom(authentication);
    }
}
